package com.acme.bankapp.domain;

import java.io.Serializable;
import java.text.DateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Logger;

import com.acme.bankapp.ClientRegistrationListeners.ClientRegistrationListener;
import com.acme.bankapp.domain.Client;
import com.acme.bankapp.exception.*;
import com.acme.bankapp.service.EmailService;

/**
 * Class of bank contains fields: listeners and clients, representing, respectively, the list of listeners and a list of clients.
 * Class methods:
 * public void printAllClients(): Print a list of clients.
 * public void printBalance(): Print a list of the bank balance sheets.
 * public void addClient(Client client) : Adding a client to the list clients.
 * public void withdrawClient(Client client, double x): Withdrawal the client balance of magnitude x.
 * public void depositeClient(Client client, double x): Increase the balance on the delta.
 * public void printClient(Client client): Print selected client.
 * public Client searchClient(String searchFirstName, String searchLastName, Gender gender): Searching for a client in the list clients.
 * The nested class DebugListener that contains the method void onAddClient(Client client) output to the console client's name and the current time.
 * The nested class PrintClientListener that contains the method void onAddClient(Client client) output to the console all information about the client.
 * The nested class EmailNotificationListener thst contains the method void onAddClient(Client client) output notification email.
 * @author Troitskaya Anastasia
 *
 */

@SuppressWarnings("serial")
public class Bank implements Serializable {
	private List<Client> clients;
    private static final Logger logger = Logger.getLogger(Bank.class.getName());
	private List<ClientRegistrationListener> listeners;
	private EmailService serv = new EmailService();
	public Bank() {
		this.clients = new LinkedList<Client>();
		this.listeners = new LinkedList<ClientRegistrationListener>();
		//listeners.add(new PrintClientListener());
		listeners.add(new EmailNotificationListener());
		listeners.add(new DebugListener());
	}
	public EmailService getServiceEmail() {
		return serv;
	}
	public List<Client> getList() {
		return clients;
	}
	public void printAllClients() {
		for (Client client: clients) {
			logger.info(client.toStringClient() + " " + client.getAccount().toString());
		}
	}
	public void printBalance() {
		for (Client client: clients) {
			logger.info(client.getAccount().toString());
		}
	}
	public void addClient(Client client) {
		assert(client != null);
		try {
			if (!(clients.contains(client))) {
				clients.add(client);
				for (ClientRegistrationListener listener: listeners) {
					listener.onClientAdd(client);
				}
			}
			else
				throw new ClientExistException();
		}
		catch (ClientExistException e) {
			logger.warning("There is this client already");
		}
	}
	public void withdrawClient(Client client, double x) {
		try {
			if (client != null) {
				try {
					client.getAccount().withdraw(x);
				}
				catch (OverDraftLimitExceededException e) {
					logger.info("There is no such money, because");
					logger.info("Balance is " + e.getBalance() + ",maxCredit is " + e.getMaxCredit());
				}
				catch (NotEnoughFundsException e) {
					logger.warning("There is no such money");
				}
			}
			else
				throw new ClientExistException();
		}
		catch (ClientExistException e) {
			logger.warning("There is no such client");
		}
	}
	public void depositeClient(Client client, double x) {
		try {
			if (client != null)
				client.getAccount().deposite(x);
			else
				throw new ClientExistException();
		}
		catch (ClientExistException e) {
			logger.warning("There is no such client");
		}
	}
	public void printClient(Client client) {
		try {
			if (client != null)
				logger.info(client.toStringClient() + " " + client.getAccount().toString());
			else
				throw new ClientExistException();
		}
		catch (ClientExistException e) {
			logger.warning("There is no such client");
		}
	}
	public Client searchClient(String searchFirstName, String searchLastName, Gender gender) {
		Client searchClient = new Client(searchFirstName, searchLastName, gender);
		for (Client client: clients) {
			if (client.equals(searchClient)) {
				return client;
			}
		}
		logger.warning("return null");
		return null;
	}
	public void delete(Client client) {
		clients.remove(client);
	}
	class DebugListener implements ClientRegistrationListener {
		public void onClientAdd(Client client) {
			DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT);
			String s = df.format(new Date());
			logger.info(client.toStringClient() + " " + s);
		}
	}
	class PrintClientListener implements ClientRegistrationListener {
		public void onClientAdd(Client client) {
			logger.info(String.valueOf(client.toStringClient()));//+" "+client.getAccount().toString());
		}
	}
	class EmailNotificationListener implements ClientRegistrationListener {
		public void onClientAdd(Client client) {
			String email = "ddd@gmail.com";
			serv.sendNotificationEmail(client, email);
			logger.info("Notification email for "+client.toStringClient()+" to be sent");
		}
	}

}
